<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        /*
            上面写的单例模式存在两个问题
                1.new关键字被省略了
                2.构造函数并没有参与到创建实例对象中来

            这里补充一下new关键字
            1.创建一个空对象
            2.将对象的原型__proto__赋值给构造函数的原型对象
            3.调用构造函数并将构造函数中的this指向obj。这里可以使用apply关键字
            4.将对象return出去即可
         */

        /*
        完善单例模式的注意事项
            1.需要想办法保留instance标识符，不然无法判断当前是否已经存在实例对象
            2.可以使用闭包的方式将instance保存下来
        */

        // 这里使用立即执行函数来创建一个闭包
        const Person = (function () {
            let instance = null;
            function Person(name, age, sex) {
                this.name = name
                this.sex = sex
                this.age = age
            }
            Person.prototype.sayHi = function () {
                console.log('Hello');
            }
            // 保存 Perosn构造函数 及 instance
            return function (...args) {
                if (!instance) instance = new Person(...args)
                return instance;
            }
        }())

        // 这里的new关键字可有可无，因为匿名函数中会return instance
        const p1 = new Person('zhangsan', 18, '男');
        const p2 = new Person();
        p1.sayHi();
        // 这里就通过单例模式创造出了两个一模一样的对象实例
        console.log(p1, p2);
        console.log(p1 === p2);

    </script>
</body>

</html>